package xpn.platform.modules.sys.user;

import com.google.common.base.Strings;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.ArrayUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.web.client.RestTemplate;
import xpn.platform.common.config.XpnPlatformConfig;
import xpn.platform.common.exception.XpnBusinessException;
import xpn.platform.common.exception.XpnExceptionCodeEnum;
import xpn.platform.common.util.Tool;
import xpn.platform.modules.sys.org.SysOrg;
import xpn.platform.modules.sys.org.SysOrgService;

import java.util.ArrayList;
import java.util.List;

/**
 * 人员服务实现
 *
 * @author bobatkm Oct 19, 2017
 */
@Service
public class SysUserServiceImpl implements SysUserService {

	private static String STARTER = "原始作者";
	private static String MYSENDER = "本人的发送人";
	private static String SPECIFIEDUSERS = "指定用户";

	@Autowired
	SysUserDAO userDao;

	@Autowired
	SysOrgService orgService;

	@Autowired
	private RestTemplate restTemplate;

	@Autowired
	XpnPlatformConfig xpnPlatformConfig;

	@Override
	public SysUser getSessionUser() {
		Subject subject = SecurityUtils.getSubject();
		if(subject!=null){
			if(subject.getPrincipals()!=null){
				return (SysUser) subject.getPrincipals().getPrimaryPrincipal();
			}
		}
		return null;
	}

	@Override
	public List<SysUser> findSendeeSelectUsers(String roleCondition, Integer ouLevel, Integer ouType, String orgId,
			String starterId, String mySenderId, String specificReceiverUrl, String xpnTokenName, String token) {
		// 情形1：未指定角色条件
		if (Strings.isNullOrEmpty(roleCondition)) {
			// 指定了orgId
			if (!Strings.isNullOrEmpty(orgId)) {
				return userDao.findByOrgId(Long.valueOf(orgId));
			}
			return new ArrayList<>();
		}

		// 情形2：指定角色
		// 根据角色条件查找所有符合条件的用户列表roleUserList，如果为空，则返回空列表
		return this.findByRoleCondition(roleCondition, ouLevel, ouType, orgId, starterId, mySenderId,
				specificReceiverUrl, xpnTokenName, token);
	}

	private List<SysUser> findByRoleCondition(String roleCondition, Integer ouLevel, Integer ouType, String orgId,
			String starterId, String mySenderId, String specificReceiverUrl, String xpnTokenName, String token) {
		List<SysUser> userList = new ArrayList<>();
		// 1 根据roleCondition构造查询jpql
		String jpql = constructQueryJpql(roleCondition);

		// 2 调用dao的filter查询符合条件的人员列表
		if (!Strings.isNullOrEmpty(jpql)) {
			userList = userDao.filterByJpql(jpql);
		}
		if (userList.size() == 0) {
			this.specialRoleCondition(roleCondition, starterId, mySenderId, specificReceiverUrl, xpnTokenName, token,
					userList);
			return userList;
		}

		if (!Strings.isNullOrEmpty(orgId)) {
			// 根据指定组织机构的id过滤
			this.specialRoleCondition(roleCondition, starterId, mySenderId, specificReceiverUrl, xpnTokenName, token,
					userList);
			userList = this.filterUsers(userList, orgId);
		} else {
			// 根据ou条件过滤用户列表
			// 获取当前用户的指定ouLevel的机构名称userOU，如果没有返回空列表
			// 获取当前用户curUser
			SysUser curUser = this.getSessionUser();
			String userOUName = this.getOUName(curUser, ouLevel);
			if (!"".equals(userOUName)) {
				// 根据ouLevel和ouType过滤
				userList = this.filterUsers(userList, userOUName, ouLevel, ouType);
			}
			this.specialRoleCondition(roleCondition, starterId, mySenderId, specificReceiverUrl, xpnTokenName, token,
					userList);
		}

		return userList;
	}

	@Override
	public List<SysUser> findByRoleCondition(String roleCondition, String starterId, String mySenderId,
			String specificReceiverUrl, String xpnTokenName, String token) {
		List<SysUser> userList = new ArrayList<>();
		// 1 根据roleCondition构造查询jpql
		String jpql = constructQueryJpql(roleCondition);

		// 2 调用dao的filter查询符合条件的人员列表
		if (!Strings.isNullOrEmpty(jpql)) {
			userList = userDao.filterByJpql(jpql);
		}
		if (userList.size() == 0) {
			this.specialRoleCondition(roleCondition, starterId, mySenderId, specificReceiverUrl, xpnTokenName, token,
					userList);
			return userList;
		}
		return userList;
	}

	/**
	 * 查询特殊角色条件
	 *
	 * @param roleCondition
	 * @param starterId
	 * @param mySenderId
	 * @param specificReceiverUrl
	 * @param xpnTokenName
	 * @param token
	 * @param userList
	 * @return
	 */
	private void specialRoleCondition(String roleCondition, String starterId, String mySenderId,
			String specificReceiverUrl, String xpnTokenName, String token, List<SysUser> userList) {
		List<SysUser> specialUsers = new ArrayList<>();
		if (roleCondition.contains(STARTER)) {
			Assert.hasLength(starterId, "starterId 不能为空值!");
			SysUser startUser = userDao.getById(Long.parseLong(starterId));
			specialUsers.add(startUser);
		}
		if (roleCondition.contains(MYSENDER)) {
			Assert.hasLength(starterId, "mySenderId 不能为空值!");
			SysUser mySenderUser = userDao.getById(Long.parseLong(mySenderId));
			specialUsers.add(mySenderUser);
		}
		if (roleCondition.contains(SPECIFIEDUSERS)) {
			Assert.hasLength(starterId, "specificReceiverUrl 不能为空值!");
			HttpHeaders httpHeaders = new HttpHeaders();
			httpHeaders.set(xpnTokenName, token);
			HttpEntity<Object> requestEntity = new HttpEntity<>(httpHeaders);
			ResponseEntity<List<SysUser>> responseEntity = restTemplate.exchange(specificReceiverUrl, HttpMethod.GET,
					requestEntity, new ParameterizedTypeReference<List<SysUser>>() {
					});
			List<SysUser> specifiedUsers = responseEntity.getBody();
			specialUsers.addAll(specifiedUsers);
		}
		for (SysUser user : specialUsers) {
			if (!userList.contains(user)) {
				userList.add(user);
			}
		}
	}

	/**
	 * 根据roleCondition构造查询jpql
	 *
	 * @param roleCondition
	 *            ：角色条件,当前全部用or连接 。示例：公司领导, 部门领导; 绩效考核(分隔符支持:空格,逗号(全角或半角),分号)
	 * @return
	 */
	private String constructQueryJpql(String roleCondition) {
		return "select distinct o from SysUser o LEFT JOIN FETCH o.roles r where r.name IN " + generateCondition(roleCondition);
	}

	private String generateCondition(String roleCondition) {
		String[] s = roleCondition.split("\\s*(,|;|\\s|，)\\s*");
		// 移除特殊角色词
		String[] roles = ArrayUtils.removeElements(s, STARTER, MYSENDER, SPECIFIEDUSERS);
		return "('" + StringUtils.join(roles, "','") + "')";
	}

	@Override
	public List<SysUser> filterUsers(List<SysUser> userList, String ouName, Integer ouLevel, Integer ouType) {
		// 未指定ou条件，不过滤
		if (Strings.isNullOrEmpty(ouName) || ouLevel < 0 || ouType < 0) {
			return userList;
		}

		List<SysUser> newUserList = new ArrayList<>();

		for (SysUser user : userList) {
			String userOUName = this.getOUName(user, ouLevel);
			if (ouType == 0 && userOUName.equals(ouName)) {
				newUserList.add(user);
			} else if (ouType == 1 && !userOUName.equals("") && !userOUName.equals(ouName)) {
				newUserList.add(user);
			}
		}
		return newUserList;
	}

	/**
	 * 根据组织机构id过滤用户列表
	 *
	 * @param userList
	 * @param orgId
	 * @return
	 */
	private List<SysUser> filterUsers(List<SysUser> userList, String orgId) {
		if (orgId == null || "".equals(orgId)) {
			return userList;
		}
		List<SysUser> newUserList = new ArrayList<>();
		for (SysUser user : userList) {
			if (user.getOrg() != null) {
				if (orgId.equals(user.getOrg().getId() + "")) {
					newUserList.add(user);
				}
			}
		}
		return newUserList;
	}

	@Override
	public String getOUName(SysUser user, int ouLevel) {
		if (ouLevel<0) {
			return "";
		}
		SysOrg org = user.getOrg();
		SysOrg ouOrg = orgService.getOUOrg(org, ouLevel);
		if (ouOrg == null) {
			return "";
		}
		return ouOrg.getOrgName();
	}

	@Override
	public String getOrgFullName(SysUser user) {
		return user.fetchOrgFullName();
	}

	@Override
	public void updatePassword(String userId, String password, String newPassword) {
		SysUser currentUser = this.getSessionUser();
		Long targetUserId = Long.valueOf(userId);
		SysUser targetUser = userDao.getById(targetUserId);

		if (targetUser == null) {
			throw new XpnBusinessException(XpnExceptionCodeEnum.BUSINESS_EXCEPTION_HTTP_STATUS, "用户不存在!");
		}

		if (!currentUser.getId().equals(Long.valueOf(userId))) { // id不匹配，继续检查userCode是相同：相同代表是兼职用户
			if (!currentUser.getUserCode().equals(targetUser.getUserCode())) {
				throw new XpnBusinessException(XpnExceptionCodeEnum.BUSINESS_EXCEPTION_HTTP_STATUS, "用户不匹配!");
			}
		}

		String pass;
		String newPass;
		String passwordDigest = xpnPlatformConfig.getSecurity().getPasswordDigest();
		if (!Strings.isNullOrEmpty(passwordDigest) && !"none".equals(passwordDigest.toLowerCase())) {
			pass = Tool.MD5(password);
			newPass = Tool.MD5(newPassword);
		} else {
			pass = password;
			newPass = newPassword;
		}
		if (!targetUser.getRealPassword().equals(pass)) {
			throw new XpnBusinessException(XpnExceptionCodeEnum.BUSINESS_EXCEPTION_HTTP_STATUS, "原密码错误!");
		}

		targetUser.setPassword(newPass);
		userDao.save(targetUser);
	}



}
